/**
 * Wihidum - Efficient Broker Hierarchy for Publish Subscribe Middleware
 *
 * License      :   Apache License 2.0
 * Home Page    :   http://code.google.com/p/wihidum/
 * Mailing List :   wihidum@googlegroups.com
 */

package lk.mrt.cse.wihidum.subscriber.client;

import org.apache.axiom.om.*;
import org.apache.axis2.*;
import org.apache.axis2.addressing.*;
import org.apache.axis2.client.*;

import javax.xml.namespace.*;
import java.util.*;

/**
 * Client invoking subscriber service
 */
public class Client
{
    private UserInterface userInterface;

    public Client(UserInterface userInterface)
    {
        this.userInterface = userInterface;
    }

    /**
     * Invoking subscribe method in subscriber service
     *
     * @param subscriptionID    ID of subscriber client
     * @param brokerAddress     Address of broker
     * @param adminAddress  Address of publisher
     * @param listenerAddress   Address of listener
     * @param subscriberAddress Address of subscriber
     * @param topic             Subscribing topic
     */
    public void subscribe(String subscriptionID, String brokerAddress, String adminAddress, String listenerAddress, String subscriberAddress, String topic)
    {
        try
        {
            ServiceClient serviceClient = new ServiceClient();
            Options options = new Options();
            options.setTo(new EndpointReference(subscriberAddress));
            options.setAction("subscribe");
            serviceClient.setOptions(options);

            OMFactory factory = OMAbstractFactory.getOMFactory();

            OMElement messageElement = factory.createOMElement("SubscriptionRequest", null);

            OMElement subscriptionHeader = factory.createOMElement("Header", null);
            OMElement actionElement = factory.createOMElement("Action", null);
            actionElement.setText("subscribe");
            subscriptionHeader.addChild(actionElement);
            messageElement.addChild(subscriptionHeader);

            OMElement subscriptionIDElement = factory.createOMElement("subscriptionID", null);
            subscriptionIDElement.setText(subscriptionID);
            messageElement.addChild(subscriptionIDElement);

            OMElement brokerAddressElement = factory.createOMElement("brokerAddress", null);
            brokerAddressElement.setText(brokerAddress);
            messageElement.addChild(brokerAddressElement);

            OMElement publisherAddressElement = factory.createOMElement("adminAddress", null);
            publisherAddressElement.setText(adminAddress);
            messageElement.addChild(publisherAddressElement);

            OMElement listenerAddressElement = factory.createOMElement("listenerAddress", null);
            listenerAddressElement.setText(listenerAddress);
            messageElement.addChild(listenerAddressElement);

            OMElement subscriberAddressElement = factory.createOMElement("subscriberAddress", null);
            subscriberAddressElement.setText(subscriberAddress);
            messageElement.addChild(subscriberAddressElement);

            OMElement topicElement = factory.createOMElement("topic", null);
            topicElement.setText(topic);
            messageElement.addChild(topicElement);

            OMElement responseElement = serviceClient.sendReceive(messageElement);

            //OMElement referenceParameters = responseElement.getFirstChildWithName(new QName("ReferenceParameters"));
            //OMElement responseTextElement = referenceParameters.getFirstChildWithName(new QName("Response"));

            userInterface.showInfo(responseElement.getText());
        }
        catch (NullPointerException ex)
        {
            userInterface.showError("Error in processing subscription response");
        }
        catch (AxisFault ex)
        {
            userInterface.showError("Error in sending subscription request");
        }
    }

    public void unsusbcribe(String listenerServiceAddress, String clientID, String filterTopic)
    {
        OMFactory factory = OMAbstractFactory.getOMFactory();

        OMElement messageElement = factory.createOMElement("UnsubscriptionRequest", null);

        OMElement actionElement = factory.createOMElement("Action", null);
        actionElement.setText("unsubscribe");
        messageElement.addChild(actionElement);

        OMElement subscriptionIDElement = factory.createOMElement("subscriptionID", null);
        subscriptionIDElement.setText(clientID);
        messageElement.addChild(subscriptionIDElement);

        OMElement topicElement = factory.createOMElement("topic", null);
        topicElement.setText(filterTopic);
        messageElement.addChild(topicElement);

        try
        {
            ServiceClient serviceClient = new ServiceClient();
            Options options = new Options();
            options.setTo(new EndpointReference(listenerServiceAddress));
            options.setAction("unsubscribe");
            serviceClient.setOptions(options);
            OMElement responseElement = serviceClient.sendReceive(messageElement);
            if(responseElement!=null)
            {
                userInterface.showInfo("Unsubscription completed successfully");
            }
            else
                userInterface.showError("No response for unsubscription");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }


    }

    public void getPublications(String subscriptionID, String subscriberAddress, String listenerAddress)
    {
        try
        {
            ServiceClient serviceClient = new ServiceClient();
            Options options = new Options();
            options.setTo(new EndpointReference(subscriberAddress));
            options.setAction("getPublications");
            serviceClient.setOptions(options);

            OMFactory factory = OMAbstractFactory.getOMFactory();

            OMElement messageElement = factory.createOMElement("GetPublicationsRequest", null);

            OMElement subscriptionHeader = factory.createOMElement("Header", null);
            OMElement actionElement = factory.createOMElement("Action", null);
            actionElement.setText("getPublications");
            subscriptionHeader.addChild(actionElement);
            messageElement.addChild(subscriptionHeader);

            OMElement subscriptionIDElement = factory.createOMElement("subscriptionID", null);
            subscriptionIDElement.setText(subscriptionID);
            messageElement.addChild(subscriptionIDElement);

            OMElement listenerAddressElement = factory.createOMElement("listenerAddress", null);
            listenerAddressElement.setText(listenerAddress);
            messageElement.addChild(listenerAddressElement);

            OMElement responseElement = serviceClient.sendReceive(messageElement);

            OMElement referenceParameters = responseElement.getFirstChildWithName(new QName("ReferenceParameters"));
            OMElement responseTextElement = referenceParameters.getFirstChildWithName(new QName("Response"));

            userInterface.clearTable();

            for (Iterator<OMElement> publicationElement = responseTextElement.getChildrenWithName(new QName("Publication")); publicationElement.hasNext();)
            {
                OMElement nextPublication = publicationElement.next();
                OMElement publisher = nextPublication.getFirstChildWithName(new QName("publisherAddress"));
                OMElement topic = nextPublication.getFirstChildWithName(new QName("topic"));
                OMElement publicationText = nextPublication.getFirstChildWithName(new QName("publicationText"));

                userInterface.newPublicationReceived(publisher.getText(), topic.getText(), publicationText.getText());
            }

            userInterface.showInfo(responseTextElement.getText());
        }
        catch (NullPointerException ex)
        {
            userInterface.showError("Error in processing get publications response");
        }
        catch (AxisFault ex)
        {
            userInterface.showError("Error in sending get publications request");
        }
    }
}
